package csc.traning.wpsj.servlet.upload;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import java.util.ListIterator;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;

import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import csc.traning.wpsj.dao.User;

/**
 * Servlet implementation class FileDownloadServlet
 */
public class FileDownloadServlet extends HttpServlet {
	private static final long serialVersionUID = 1L;

	/**
	 * @see HttpServlet#HttpServlet()
	 */
	public FileDownloadServlet() {
		super();
		// TODO Auto-generated constructor stub
	}

	/**
	 * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse
	 *      response)
	 */
	protected void doGet(HttpServletRequest request,
			HttpServletResponse response) throws ServletException, IOException {
		HttpSession session = request.getSession();
		User user = (User) session.getAttribute("user");
		if (user == null) {
			throw new ServletException("Required to login");
		}
		try {
			String userPath = "users/" + user.getUserName() + "/file_uploaded";
			String realUserPath = getServletContext().getRealPath(userPath);
			String currentDir = (String) session.getAttribute("currentDir");
			String[] selectFile = request.getParameterValues("fileSelect");
			
			List<File> fileList = new ArrayList<File>();
			
			
			if (!(selectFile == null || selectFile.length < 1)) {
				for (int i = 0; i < selectFile.length; i++) {

					String realPath = realUserPath + selectFile[i];
					File filedownload = new File(realPath);
					getAllFiles(filedownload,fileList);
				}
			} else {
				request.setAttribute("forwardDir", currentDir);
				RequestDispatcher dispatcher = request.getRequestDispatcher("file-management");
				dispatcher.forward(request, response);
			}


	

			if (fileList != null && fileList.size() > 0) {
				byte[] zip = writeZipFile(new File(realUserPath+currentDir), fileList);
				ServletOutputStream sos = response.getOutputStream();

				// Let Browser understand the zip file
				response.setContentType("application/zip");
				response.setHeader("Content-Disposition",
						"attachment; filename=\"downloads.zip\"");
				sos.write(zip);
				sos.flush();
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	/**
	 * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse
	 *      response)
	 */
	protected void doPost(HttpServletRequest request,
			HttpServletResponse response) throws ServletException, IOException {
		doGet(request, response);
	}

	public static void getAllFiles(File dir, List<File> fileList) {
		if (dir.isDirectory()) {
			File[] files = dir.listFiles();
			for (File file : files) {
				fileList.add(file);
				if (file.isDirectory()) {
					getAllFiles(file, fileList);
				}
			}
		} else if (dir != null) {
			fileList.add(dir);
		}

	}

	public static byte[] writeZipFile(File directoryToZip, List<File> fileList) {

		try {
			ByteArrayOutputStream baos = new ByteArrayOutputStream();
			ZipOutputStream zos = new ZipOutputStream(baos);

			for (File file : fileList) {
				if (!file.isDirectory()) { // we only zip files, not directories
					addToZip(directoryToZip, file, zos);
				}
			}

			zos.close();
			baos.close();

			return baos.toByteArray();
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}

		return null;
	}

	public static void addToZip(File directoryToZip, File file,
			ZipOutputStream zos) throws FileNotFoundException, IOException {

		FileInputStream fis = new FileInputStream(file);

		// we want the zipEntry's path to be a relative path that is relative
		// to the directory being zipped, so chop off the rest of the path
		String zipFilePath = file.getCanonicalPath().substring(
				directoryToZip.getCanonicalPath().length() + 1,
				file.getCanonicalPath().length());
		ZipEntry zipEntry = new ZipEntry(zipFilePath);
		zos.putNextEntry(zipEntry);

		byte[] bytes = new byte[1024];
		int length;
		while ((length = fis.read(bytes)) >= 0) {
			zos.write(bytes, 0, length);
		}

		zos.closeEntry();
		fis.close();
	}

}
